ArrayList

O ArrayList é uma das classes mais utilizadas da biblioteca Java Collections Framework.


Definição sobre estruturas de dados em Java:

https://www.devmedia.com.br/java-collections-como-utilizar-collections/18450

https://www.w3schools.com/java/java_data_structures.asp

https://www.w3schools.com/java/java_collections.asp


Um ArrayList em Java é uma estrutura de dados da biblioteca padrão (java.util) que representa uma lista de tamanho dinâmico. Diferentemente de um array tradicional, cujo tamanho precisa ser definido no momento da criação e não pode ser alterado, o ArrayList consegue crescer e diminuir automaticamente conforme elementos são adicionados ou removidos.


Relação com arrays tradicionais


Internamente, o ArrayList utiliza um array comum para armazenar seus elementos. Ou seja, apesar de oferecer uma interface mais flexível para o programador, ele ainda depende do mesmo conceito básico de memória contígua utilizado pelos arrays em Java.


Quando um ArrayList é criado, ele possui uma capacidade inicial, que representa quantos elementos podem ser armazenados antes que seja necessário um redimensionamento. Essa capacidade não é o mesmo que o tamanho lógico da lista (quantidade de elementos realmente inseridos).


Redimensionamento do array interno


O ponto-chave do funcionamento do ArrayList é o redimensionamento automático. Quando o array interno atinge sua capacidade máxima e um novo elemento é adicionado, o ArrayList realiza os seguintes passos:


1. Cria um novo array maior na memória.

2. Copia todos os elementos do array antigo para o novo.

3. Substitui o array interno antigo pelo novo.


Esse processo é transparente para o programador, mas tem um custo computacional, pois envolve alocação de memória e cópia de dados. Por isso, a adição de elementos em um ArrayList é considerada, em média, eficiente (O(1) amortizado), mas pode ocasionalmente ser mais custosa quando ocorre o redimensionamento.


Crescimento da capacidade


O Java não aumenta o array interno apenas em uma posição. Em geral, ele cresce de forma proporcional (aproximadamente 50% a mais da capacidade atual), reduzindo a frequência de redimensionamentos e melhorando o desempenho em operações de inserção contínua.


Além disso, o programador pode definir uma capacidade inicial ao criar o ArrayList, o que é útil quando já se sabe previamente a quantidade aproximada de elementos:


ArrayList<String> nomes = new ArrayList<>(100);


Conclusão


Em resumo, o ArrayList é uma abstração poderosa sobre arrays tradicionais. Ele simplifica o gerenciamento de tamanho ao automatizar o redimensionamento do array interno, permitindo maior flexibilidade no desenvolvimento de aplicações. No entanto, entender que esse redimensionamento existe é fundamental para escrever código mais eficiente, especialmente em cenários com grande volume de dados ou muitas inserções.


O ArrayList armazena apenas objetos (não tipos primitivos diretamente), mantém a ordem de inserção dos elementos e permite elementos duplicados. Ele pertence ao pacote java.util e implementa a interface List.


Criação de um ArrayList


Para usar um ArrayList, é necessário importá-lo e definir o tipo de dados que ele irá armazenar:

import java.util.ArrayList;

ArrayList<String> nomes = new ArrayList<>();

Nesse exemplo, o ArrayList nomes armazena objetos do tipo String. O uso dos símbolos < > implementa o conceito de generics. Sem o uso deste conceito seria necessário aplicar o casting para converter o objeto para o tipo correto da variável. O exemplo abaixo descreve como seria o exemplo sem gerenerics.


import java.util.ArrayList;

ArrayList<String> nomes = new ArrayList();

nomes.add(new String("Maria"));
String p = (String) nomes.get(0); // cast obrigatório


Métodos Descrição
add() 
Adiciona elementos ao fim da lista.
get()  
Retorna o elemento de uma posição específica.
set()
Substitui um elemento em uma determinada posição.
remove() 
Remove um elemento em uma determinada posição.
size()
Retorna a quantidade de elementos existentes na lista.


Adicionando elementos


Os elementos são adicionados com o método add():

nomes.add("Ana");
nomes.add("Carlos");
nomes.add("Ana");

Note que valores duplicados são permitidos.


Acessando elementos


Os elementos são acessados por meio do índice, começando do zero, usando o método get():

System.out.println(nomes.get(0)); // Ana


Alterando elementos


Para alterar um valor em uma posição específica, utiliza-se o método set():

nomes.set(1, "João");


Removendo elementos


Um elemento pode ser removido pelo índice ou pelo próprio valor:

nomes.remove(0);        // remove pelo índice
nomes.remove("Ana");    // remove a primeira ocorrência do valor


Tamanho do ArrayList


O método size() retorna a quantidade de elementos armazenados:

System.out.println(nomes.size());


Percorrendo um ArrayList


Uma forma comum de percorrer os elementos é usando um laço for-each:

for (String nome : nomes) {
    System.out.println(nome);
}


Conclusão


O ArrayList é ideal quando se precisa de uma estrutura flexível, com acesso rápido aos elementos por índice. No entanto, ele pode ter desempenho inferior em operações frequentes de inserção ou remoção no meio da lista, pois os elementos precisam ser reorganizados.